package controllers.admin;

import java.util.ArrayList;
import java.util.List;

import models.Administrator;
import models.Attachment;
import models.BaseEntity.Status;
import models.Brand;
import models.Commodity;
import models.Commodity.ChangeQuantityWay;
import models.Commodity.OnSaleStatus;
import models.CommodityImage;
import models.PricedCommodity;
import models.QueryBean;
import models.UserGroup;
import models.UserGroup.UserGroupType;
import play.Logger;
import play.data.validation.Required;
import play.data.validation.Valid;
import play.mvc.Controller;
import play.mvc.With;
import service.CommoditiesService;
import controllers.GlobalVariables;
import controllers.Secure;
import controllers.ValidationUtil;

/**
 * 商品模块控制器
 * 
 * @author justin
 *
 */
@With(Secure.class)
public class Commodities extends Controller {
	//----------管理－－－－－－－－－－－

	/**
	 * 商品管理页面
	 */
	public static void index(){
		int page = params.get("page", Integer.class) != null ? params.get("page", Integer.class) : 1;
		int pageSize = params.get("pageSize", Integer.class) != null ? params.get("pageSize", Integer.class) : 10;
		long totalCount = Commodity.count();
		List<Commodity> commodities = Commodity.all().fetch(page, pageSize);
		
		if(request.isAjax())
		{
			render("tags/commodities/_table.html", page, pageSize, totalCount, commodities);
		} else 
		{
			render(page, pageSize, totalCount, commodities);
		}
	}
	
	//POST	/admin/commodities;admin
	public static void indexTable(QueryBean queryBean, OnSaleStatus onSaleStatus) {
		if(queryBean == null) {
			queryBean = new QueryBean();
			queryBean.isDesc = true;
		}
		StringBuilder hql = new StringBuilder("id != null ");
    	List<Object> objs = new ArrayList<Object>();
    	
    	if(onSaleStatus != null) {
    		hql.append(" and onSaleStatus = ? ");
    		objs.add(onSaleStatus);
    	}
    	
    	if(!ValidationUtil.isEmpty(queryBean.keyword)) {
    		if(ValidationUtil.isLong(queryBean.keyword)) {
    			hql.append("and (id=? or ");
        		objs.add(Long.valueOf(queryBean.keyword));
    		} else {
    			hql.append("and ( ");
    		}
    		hql.append("name like ? or SN like ? or manufacturerSN like ?) ");
    		objs.add("%"+queryBean.keyword+"%");
    		objs.add("%"+queryBean.keyword+"%");
    		objs.add("%"+queryBean.keyword+"%");
    	}
    	
    	if(!ValidationUtil.isEmpty(queryBean.orderby)) {
    		hql.append(" order by " + queryBean.orderby);
    		if(queryBean.isDesc) 
    			hql.append(" desc ");
    		else
    			hql.append(" asc ");
    	} else {
    		hql.append(" order by createAt desc, lastModifiedAt desc ");
    	}
		
		//页数计算
		queryBean.totalQuantity = Commodity.count(hql.toString(), objs.toArray());
		queryBean.totalPage = (queryBean.totalQuantity/queryBean.quantityEachPage + 1);
		if(queryBean.totalPage < queryBean.currentPage) {
			queryBean.currentPage = queryBean.totalPage;
		}
		
		List<Commodity> commodities = Commodity.find(hql.toString(), objs.toArray()).fetch(
				(int)queryBean.currentPage, queryBean.quantityEachPage);
		CommoditiesService.setCommodityPriceByUser(commodities, null);
		
		render(commodities, queryBean);
	}
	
	//GET /commodities;new
	public static void blank(){
		Commodity commodity = new Commodity();
		List<Brand> brands = getEnableBrands(null);
		render("admin/Commodities/new.html", commodity, brands);
	}

	//POST /commodities
	public static void create(@Valid Commodity commodity, @Required Attachment att, @Required double price) {
		if(validation.hasErrors()) {
//			params.flash();
//			validation.keep();
			List<Brand> brands = null;
			if(commodity.brand != null) {
				brands = getEnableBrands(commodity.brand.id);
			} else {
				brands = getEnableBrands(null);
			}
			render("admin/Commodities/new.html", commodity, att, brands, price);
		}
		
		att = Attachment.findById(att.id);
		att.used = true;
		att.save();
		
		CommodityImage ci = new CommodityImage();
		ci.image = att;
		ci.sequence = 1;
		
		String username = session.get(GlobalVariables.SECURE_ADMINNAME);
		Administrator admin = Administrator.find("byUsername", username).first();
		commodity.setCreator(admin);
		commodity.resetModifier(admin);
		commodity.images = new ArrayList<CommodityImage>();
		commodity.images.add(ci);
		ci.commodity = commodity;
		commodity.save();
		
		UserGroup userGroup = UserGroup.find("isDefault=?", true).first();
		PricedCommodity priceCommodity = new PricedCommodity();
		priceCommodity.commodity = commodity;
		priceCommodity.group = userGroup;
		priceCommodity.price = price;
		priceCommodity.setCreator(admin);
		priceCommodity.resetModifier(admin);
		priceCommodity.save();
		
		index();
	}
	

	//GET /commodities/{id};edit
	public static void edit(Long id){
		Commodity commodity = Commodity.findById(id);
		
		List<Brand> brands = null;
		if(commodity.brand != null) {
			brands = getEnableBrands(commodity.brand.id);
		} else {
			brands = getEnableBrands(null);
		}

		render(commodity, brands);
	}
	
	
	//PUT /commodities/{id}
	public static void update(@Valid Commodity commodity){
		if(validation.hasErrors()) {
			params.flash();
			validation.keep();
			List<Brand> brands = null;
			if(commodity.brand != null) {
				brands = getEnableBrands(commodity.brand.id);
			} else {
				brands = getEnableBrands(null);
			}
			render("admin/Commodities/edit.html", commodity, brands);
		}
		Logger.info("保存商品:", commodity);
		String username = session.get(GlobalVariables.SECURE_ADMINNAME);
		Administrator admin = Administrator.find("byUsername", username).first();
		
		Commodity oriCommodity = Commodity.findById(commodity.id);
		oriCommodity.name = commodity.name;
		oriCommodity.SN = commodity.SN;
		oriCommodity.manufacturerSN = commodity.manufacturerSN;
		oriCommodity.unit = commodity.unit;
		oriCommodity.size = commodity.size;
		oriCommodity.material = commodity.material;
		oriCommodity.placeOfOrigin = commodity.placeOfOrigin;
		oriCommodity.packaging = commodity.packaging;
		oriCommodity.numberPerBox = commodity.numberPerBox;
		oriCommodity.cost = commodity.cost;
		oriCommodity.weight = commodity.weight;
		oriCommodity.grossWeight = commodity.grossWeight;
		oriCommodity.netWeight = commodity.netWeight;
		oriCommodity.description = commodity.description;
		oriCommodity.resetModifier(admin);
		oriCommodity.save();
		index();
	}
	
	//DELETE /commodities/{id}
	public static void destroy(Long id){
		Commodity.delete("id", id);
		index();
	}
	
	private static List<Brand> getEnableBrands(Long selectedBrands) {
		List<Brand> brands = Brand.find("status=?", Status.ENABLE).fetch();
		if(brands == null) {
			brands = new ArrayList<Brand>();
		}
		if(ValidationUtil.isEmpty(selectedBrands)) return brands;
		
		Brand brand = Brand.findById(selectedBrands);
		if(brand != null && brand.status == Status.DISABLED) {
			brands.add(brand);
		}
		return brands;
	}
	
	/**
	 * 更改货存数量。
	 * @param id
	 * @return
	 */
	public static void editQuantity(long id , ChangeQuantityWay changeQuantityWay) {
		Commodity commodity = Commodity.findById(id);
		render(commodity, changeQuantityWay);
	}
	
	/**
	 * 保存更改存货数量。
	 * @param commodity
	 * @param changeQuantityWay
	 */
	public static void updateQuantity(Commodity commodity,
			ChangeQuantityWay changeQuantityWay, long quantityLeft) {
		if(validation.hasErrors()) {
			params.flash();
			validation.keep();
			render("admin/Commodities/editQuantity.html", commodity);
		}
		String username = session.get(GlobalVariables.SECURE_ADMINNAME);
		Administrator admin = Administrator.find("byUsername", username).first();
		CommoditiesService.changeCommodityLeft(commodity.id, commodity.onSaleStatus, 
				changeQuantityWay, quantityLeft, admin);
		
		editQuantity(commodity.id, changeQuantityWay);
	}
	
	/**
	 * 更改商品状态。
	 * @param id
	 * @param status
	 * @throws Exception
	 */
	public static void updateStatus(long id, Status status) throws Exception {
		Commodity commodity = Commodity.findById(id);
		if(commodity == null) {
			throw new Exception("没有此商品。");
		} else {
			String username = session.get(GlobalVariables.SECURE_ADMINNAME);
			Administrator admin = Administrator.find("byUsername", username).first();
			commodity.status = status;
			commodity.resetModifier(admin);
			commodity.save();
		}
	}
	
	/**
	 * 设置价格。
	 * @param id
	 */
	public static void editPrice(long id) {
		Commodity commodity = Commodity.findById(id);
		List<UserGroup> userGroups = UserGroup.find("type = ?", UserGroupType.INHERENCE).fetch();
		render(commodity, userGroups);
	}
	
	/**
	 * 获取价格列表。
	 * @param queryBean
	 * @param id
	 */
	public static void editPriceTable(QueryBean queryBean, long id) {
		if(queryBean == null) {
			queryBean = new QueryBean();
			queryBean.isDesc = true;
		}
		StringBuilder hql = new StringBuilder("commodity.id = ? ");
    	List<Object> objs = new ArrayList<Object>();
    	objs.add(id);
    	
    	if(!ValidationUtil.isEmpty(queryBean.orderby)) {
    		hql.append(" order by " + queryBean.orderby);
    		if(queryBean.isDesc) 
    			hql.append(" desc ");
    		else
    			hql.append(" asc ");
    	} else {
    		hql.append(" order by createAt desc, lastModifiedAt desc ");
    	}
		
		//页数计算
		queryBean.totalQuantity = PricedCommodity.count(hql.toString(), objs.toArray());
		queryBean.totalPage = (queryBean.totalQuantity/queryBean.quantityEachPage + 1);
		if(queryBean.totalPage < queryBean.currentPage) {
			queryBean.currentPage = queryBean.totalPage;
		}
		List<PricedCommodity> pricedCommodities = PricedCommodity.find(hql.toString(), objs.toArray()).fetch(
				(int)queryBean.currentPage, queryBean.quantityEachPage);
		
		render(pricedCommodities, queryBean);
	}
	
	/**
	 * 保存价格。
	 * @param pricedCommodity
	 */
	public static void updatePriceTable(PricedCommodity pricedCommodity) {
		PricedCommodity oriPC = PricedCommodity.find("commodity.id = ? and group.id = ?", 
				pricedCommodity.commodity.id, pricedCommodity.group.id).first();
		
		String username = session.get(GlobalVariables.SECURE_ADMINNAME);
		Administrator admin = Administrator.find("byUsername", username).first();
		if(oriPC != null) {
			oriPC.price = pricedCommodity.price;
			oriPC.resetModifier(admin);
			oriPC.save();
		} else {
			pricedCommodity.setCreator(admin);
			pricedCommodity.resetModifier(admin);
			pricedCommodity.save();
		}
	}
	
	/**
	 * 更改商品价格状态。
	 * @param id
	 * @param status
	 * @throws Exception
	 */
	public static void updatePriceStatus(long id, Status status) throws Exception {
		PricedCommodity pricedCommodity = PricedCommodity.findById(id);
		if(pricedCommodity.group.isDefault == true && status == Status.DISABLED) {
			throw new Exception("不能禁用默认价格。");
		} else {
			String username = session.get(GlobalVariables.SECURE_ADMINNAME);
			Administrator admin = Administrator.find("byUsername", username).first();
			pricedCommodity.status = status;
			pricedCommodity.resetModifier(admin);
			pricedCommodity.save();
		}
	}
	
	/**
	 * 查看指定商品的图片。
	 * 
	 * @param id
	 */
	public static void indexImages(long id) {
		List<CommodityImage> commodityImages = CommodityImage.find("commodity.id=? order by sequence", id).fetch();
		render(commodityImages, id);
	}
	
	/**
	 * 新增商品图片。
	 * @param commodityId
	 * @param attId
	 */
	public static void addImages(long commodityId, long attId) {
		Commodity commodity = Commodity.findById(commodityId);
		if(commodity == null) indexImages(commodityId);
		
		Attachment attachment = Attachment.findById(attId);
		if(attachment == null) indexImages(commodityId);
		
		String username = session.get(GlobalVariables.SECURE_ADMINNAME);
		Administrator admin = Administrator.find("byUsername", username).first();
		
		attachment.resetModifier(admin);
		attachment.used = true;
		attachment.save();
		
		int sequece = 0;
		if(commodity.images != null) sequece = commodity.images.size() + 1;
		CommodityImage ci = new CommodityImage();
		ci.image = attachment;
		ci.sequence = sequece;
		ci.commodity = commodity;
		ci.save();
		indexImages(commodityId);
	}
	
	/**
	 * 图片顺序上移。
	 * @param commodityId
	 * @param commodityImageId
	 */
	public static void updateSequence(long commodityId, long commodityImageId, boolean isUp) {
		Commodity commodity = Commodity.findById(commodityId);
		CommodityImage ci = CommodityImage.findById(commodityImageId);
		int minSequence = 0;
		int maxSequence = 0;
		if(commodity != null && !ValidationUtil.isEmpty(commodity.images)) {
			minSequence = 1;
			maxSequence = commodity.images.size();
		}
		if(isUp && ci.sequence == minSequence) indexImages(commodityId);
		if(!isUp && ci.sequence == maxSequence) indexImages(commodityId);
		
		if(isUp) {
			CommodityImage ciUp = CommodityImage.find("commodity.id=? and sequence = ? order by sequence", 
					commodityId, (ci.sequence - 1)).first();
			ci.sequence = ci.sequence-1;
			ci.save();
			ciUp.sequence = ciUp.sequence+1;
			ciUp.save();
		} else {
			CommodityImage ciDown = CommodityImage.find("commodity.id=? and sequence = ? order by sequence", 
					commodityId, (ci.sequence + 1)).first();
			ci.sequence = ci.sequence+1;
			ci.save();
			ciDown.sequence = ciDown.sequence-1;
			ciDown.save();
		}
		indexImages(commodityId);
	}
	
	/**
	 * 删除指定的商品图片。
	 * @param commodityId
	 * @param commodityImageId
	 * @throws Exception 
	 */
	public static void deleteCommodityImage(long commodityId, long commodityImageId) throws Exception {
		Commodity commodity = Commodity.findById(commodityId);
		CommodityImage ci = CommodityImage.findById(commodityImageId);
		if(ci == null || commodity == null) throw new Exception("图片（"+commodityImageId+"）已经被删除。");
		if(commodity.images != null && commodity.images.size()==1)
			throw new Exception("不能删除上商品的最后一张图片");
		
		Attachment image = ci.image;
		image.used = false;
		image.save();
		
		
		List<CommodityImage> cis =  CommodityImage.find("commodity.id=? and sequence>? order by sequence", 
				commodityId, ci.sequence).fetch();
		if(!ValidationUtil.isEmpty(cis)) {
			for(CommodityImage commodityImage : cis) {
				commodityImage.sequence=commodityImage.sequence-1;
				commodityImage.save();
			}
		}
		ci.commodity = null;
		ci.image = null;
		ci.save();
		ci.delete();
	}
}
